package vn.demand.dragon.view
{
	import com.adobe.utils.StringUtil;
	import com.salesbuilder.controls.DateField;
	
	import flash.events.ContextMenuEvent;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuItem;
	import flash.ui.Keyboard;
	
	import flexed.widgets.alerts.alert;
	
	import mx.collections.ICollectionView;
	import mx.collections.IViewCursor;
	import mx.controls.AdvancedDataGrid;
	import mx.controls.Alert;
	import mx.controls.CheckBox;
	import mx.controls.TextInput;
	import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
	import mx.controls.advancedDataGridClasses.AdvancedDataGridItemRenderer;
	import mx.core.UIComponent;
	import mx.events.AdvancedDataGridEvent;
	import mx.events.AdvancedDataGridEventReason;
	import mx.events.CloseEvent;
	import mx.events.ValidationResultEvent;
	import mx.validators.Validator;
	
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	import vn.demand.dragon.FFIAApplicationFacade;
	import vn.demand.dragon.editor.EditorComboBox;
	import vn.demand.dragon.model.MasterdataProxy;
	import vn.demand.dragon.model.ProjectItemProxy;
	import vn.demand.dragon.model.UserProxy;
	import vn.demand.dragon.view.components.ProjectItemScreen;
	import vn.demand.utils.DpUtils;

	public class ProjectItemScreenMediator extends Mediator
	{
		public static const NAME:String = "ProjectItemScreenMediator";
		
		private var masterdataProxy:MasterdataProxy;
		private var pitemProxy:ProjectItemProxy;
		private var userProxy:UserProxy;
		
		private var projectVO:Object;
		
		public static function makeId(projectVO:Object):String {
        	return NAME + projectVO.project_id + "::";
        }
		
		public function ProjectItemScreenMediator(projectVO:Object, mediatorName:String, viewComponent:Object)
		{
			super(mediatorName, viewComponent);
			
			this.projectVO = projectVO;
			
			masterdataProxy = facade.retrieveProxy(MasterdataProxy.NAME) as MasterdataProxy;
			pitemProxy = facade.retrieveProxy(ProjectItemProxy.makeId(projectVO)) as ProjectItemProxy;
			userProxy = facade.retrieveProxy(UserProxy.NAME) as UserProxy;
			
			projectItemScreen.addEventListener(ProjectItemScreen.PROJECT_ITEM_SCREEN_UI_CREATED, prepareData);
			
		}
		
		public function prepareData(event:Event):void {
			for each (var col:AdvancedDataGridColumn in gridProjectItems.columns) {
				switch (col.dataField) {
					case 'pitem_item_id':
					case 'pitem_container':
					case 'pitem_currency':
					case 'pitem_quantity_unit':
					case 'pitem_weight_unit':
					case 'pitem_volume_unit':
						col.labelFunction = comboBoxLabelFunction;
						break;
					case 'pitem_inspection':
					case 'pitem_unloading':
						col.labelFunction = DpUtils.lfBooleanValue;
						break;
					case 'pitem_stamp_date':
					case 'pitem_custom_date':
					case 'pitem_ETA_date':
					case 'pitem_delivery_date':
						col.labelFunction = DpUtils.lfDateValue;
						break;
					case 'line_no':
						col.labelFunction = lfRowNum;
						break;
				}
			}
			
			projectItemScreen.addEventListener(ProjectItemScreen.SAVE_PROJECT_ITEM, onSaveProjectItem);
			projectItemScreen.addEventListener(ProjectItemScreen.RELOAD_PROJECT_ITEM, onReloadProjectItem);
			projectItemScreen.addEventListener(ProjectItemScreen.BROWSE_REFERENCE, onBrowseReference);
			projectItemScreen.addEventListener(ProjectItemScreen.REMOVE_PROJECT_ITEM, onRemoveProjectItem);
			projectItemScreen.addEventListener(ProjectItemScreen.CLOSE_PROJECT_ITEM, onCloseProjectItem);
			
			gridProjectItems.addEventListener(AdvancedDataGridEvent.ITEM_EDIT_BEGIN, makeEditor);
			gridProjectItems.addEventListener(AdvancedDataGridEvent.ITEM_EDIT_END, processData);
			
			createContextMenu();
			
			gridProjectItems.contextMenu = m;
			
			doLoadProjectItems();
			
			if (!DpUtils.isTrue(userProxy.userInfo.project_edit) || masterdataProxy.isProjectCompleted(this.projectVO)) {
				userProxy = facade.retrieveProxy(UserProxy.NAME) as UserProxy;
				projectItemScreen.canEdit = false;
				removeMenu.enabled = false;
			}
		}
		
		public function onRemoveProjectItem(event:Event):void {
			doRemoveProjectItem(gridProjectItems.selectedIndex);
		}
		
		public function onBrowseReference(event:Event) {
			sendNotification(FFIAApplicationFacade.BROWSE_REFERENCE_LIST);
		}
		
		private function onCloseProjectItem(event:Event):void {
        	sendNotification(FFIAApplicationFacade.CLOSE_PROJECT_PANEL, null, ProjectPanelMediator.makeId(projectVO));
        }
		
		var m:ContextMenu;
		var copyMenu:ContextMenuItem;
        var pasteMenu:ContextMenuItem;
        var removeMenu:ContextMenuItem;
        
        private function createContextMenu():void {
		    m = new ContextMenu();
		    m.hideBuiltInItems();
		    var customItemsArr:Array = new Array();
		    copyMenu = new ContextMenuItem("Copy Row");
		    pasteMenu = new ContextMenuItem("Patse Row");
		    removeMenu = new ContextMenuItem("Remove Row");
		    
		    copyMenu.addEventListener("menuItemSelect", copyHandler);
		    pasteMenu.addEventListener("menuItemSelect", pasteHandler);
		    removeMenu.addEventListener("menuItemSelect", removeHandler);
		    
		    pasteMenu.enabled = false;
		    
		    customItemsArr.push(copyMenu);
		    customItemsArr.push(pasteMenu);
		    customItemsArr.push(removeMenu);
		    
		    m.customItems = customItemsArr;
	    }
	    
	    private var copyItem:Object = null;
	    
	    private function copyHandler(e:ContextMenuEvent):void
	    {
	    	var itemIndex:Number = -1;
	    	if (e.mouseTarget is AdvancedDataGridItemRenderer) {
		    	itemIndex = AdvancedDataGridItemRenderer(e.mouseTarget).listData.rowIndex;
	    	} else {
	    		itemIndex = gridProjectItems.selectedIndex;
	    	}
	    	if (itemIndex < 0) return;
	    	pasteMenu.enabled = true;	    	
		    copyItem = gridProjectItems.dataProvider.getItemAt(itemIndex);
	    }
	    
	    private function pasteHandler(e:ContextMenuEvent):void
	    {
	    	if (masterdataProxy.isProjectCompleted(this.projectVO)) {
	    		return;
			}
		    var itemIndex:Number = -1;
	    	if (e.mouseTarget is AdvancedDataGridItemRenderer) {
		    	itemIndex = AdvancedDataGridItemRenderer(e.mouseTarget).listData.rowIndex;
	    	} else {
	    		itemIndex = gridProjectItems.selectedIndex;
	    	}
	    	if (itemIndex < 0) return;
	    	pitemProxy.copyProjectItem(projectVO, copyItem, itemIndex);
	    	projectItemScreen.enableSave = true;
	    }
	    
	    private function removeHandler(e:ContextMenuEvent):void
	    {
	    	if (masterdataProxy.isProjectCompleted(this.projectVO)) {
	    		return;
			}
	    	var itemIndex:Number = -1;
	    	if (e.mouseTarget is AdvancedDataGridItemRenderer) {
		    	itemIndex = AdvancedDataGridItemRenderer(e.mouseTarget).listData.rowIndex;
	    	} else {
	    		itemIndex = gridProjectItems.selectedIndex;
	    	}
	    	if (itemIndex < 0) {
	    		alert.error("You don't select any row to remove!");
	    		return;
	    	}
		    doRemoveProjectItem(itemIndex);
	    }
		
		function onSaveProjectItem(event:Event):void {
			doSaveProjectItem();
		}
		
		function doSaveProjectItem():Boolean {
			if (!doValidate()) {
				alert.error(gridProjectItems.errorString);
				return false;
			}
			projectItemScreen.enableSave = false;
			
			var cursor:IViewCursor = ICollectionView(gridProjectItems.dataProvider).createCursor();
        	while (!cursor.afterLast) {
        		RIALogger.debug(this, "remove?: pitem_item_id: " + Number(cursor.current['pitem_item_id']));
        		if ((Number(cursor.current['pitem_item_id']) <= 0)) {
        			cursor.remove();
        		} else {
        			cursor.moveNext();
        		}
        	} 
			
			pitemProxy.saveProjectItems();
			return true;
		}
		
		function onReloadProjectItem(event:Event):void {
			if (projectItemScreen.enableSave) {
	        	alert.confirm("Data has being edited, do you want to reload?", function(e:CloseEvent) {
	        		if (e.detail == Alert.YES) {
	        			sendNotification(FFIAApplicationFacade.REFRESH_PITEMS, null, projectVO.project_id);	        			
	        		}
	        	});
        	} else {
        		sendNotification(FFIAApplicationFacade.REFRESH_PITEMS, null, projectVO.project_id);
        	}			
		}
		
		public function get projectItemScreen():ProjectItemScreen
		{
            return viewComponent as ProjectItemScreen;
        }
        
        public function get gridProjectItems():AdvancedDataGrid {
			return projectItemScreen.gridProjectItem;
		}
		
		public function doValidate():Boolean {
        	var errors:String = "";
        	var i:int = 1;
        	for each (var item:Object in gridProjectItems.dataProvider) {
        		if (Number(item.pitem_item_id) == 0 || Number(item.pitem_item_id) == NaN) {
        			continue;
        		}
        		if (StringUtil.trim(item.pitem_invoice_no) == '' && StringUtil.trim(item.pitem_PO_no) == '') {
        			errors += 'Row [' + i + ']: Invoice No. or P/O No. can not be empty\n';
        		}
        		if (DpUtils.parseDate(item.pitem_stamp_date) == null) {
        			errors += 'Row [' + i + ']: Stamp date is required\n';
        		}
        		if (DpUtils.parseDate(item.pitem_custom_date) == null) {
        			errors += 'Row [' + i + ']: Custom date is required\n';
        		}
        		if (DpUtils.parseDate(item.pitem_ETA_date) == null) {
        			errors += 'Row [' + i + ']: ETA date is required\n';
        		}
        		if (DpUtils.parseDate(item.pitem_delivery_date) == null) {
        			errors += 'Row [' + i + ']: Delivery date is required\n';
        		}
        		if (StringUtil.trim(item.pitem_delivery_location) == '') {
        			errors += 'Row [' + i + ']: Delivery location can not be empty\n';
        		}
        		i++;
        	}
        	if (errors.length > 0) {
        		gridProjectItems.errorString = errors;
        		return false;
        	}
    		gridProjectItems.errorString = "";
    		return true;
        }
        
		/**
         * List all notifications this Mediator is interested in.
         * <P>
         * Automatically called by the framework when the mediator
         * is registered with the view.</P>
         * 
         * @return Array the list of Nofitication names
         */
        override public function listNotificationInterests():Array 
        {
            return [ 
            	FFIAApplicationFacade.REFERENCE_SELECTED,
            	FFIAApplicationFacade.LOAD_PITEMS_BY_REFERENCE_FAILED,
            	FFIAApplicationFacade.LOAD_PITEMS_BY_REFERENCE_SUCCESS,
            	FFIAApplicationFacade.PROJECT_ITEM_UPDATED,
            	FFIAApplicationFacade.REFRESH_PITEMS
			];
        }
        
        /**
         * Handle all notifications this Mediator is interested in.
         * <P>
         * Called by the framework when a notification is sent that
         * this mediator expressed an interest in when registered
         * (see <code>listNotificationInterests</code>.</P>
         * 
         * @param INotification a notification 
         */
        override public function handleNotification( note:INotification ):void 
        {
        	RIALogger.debug(this, "handleNotification: " + Number(projectVO.project_id));
        	if (Number(note.getType()) != Number(projectVO.project_id)) {
        		return;
        	}
            switch ( note.getName() ) 
			{
				case FFIAApplicationFacade.LOAD_PITEMS_BY_REFERENCE_SUCCESS:
                	pitemProxy.pitemsDP.addItem(pitemProxy.newProjectItem());
                	gridProjectItems.dataProvider = pitemProxy.pitemsDP;
                	gridProjectItems.errorString = null;
                	this.projectItemScreen.enableSave = false;
                	break;
				case FFIAApplicationFacade.LOAD_PITEMS_BY_REFERENCE_FAILED:
                	gridProjectItems.errorString = note.getBody().toString();
                	break;
				case FFIAApplicationFacade.PROJECT_ITEM_UPDATED:
					alert.info("Reference lines updated");
					pitemProxy.pitemsDP.addItem(pitemProxy.newProjectItem());
					gridProjectItems.errorString = null;
                	this.projectItemScreen.enableSave = false;
					break;
				case FFIAApplicationFacade.PROJECT_UPDATE_FAILED:
					alert.error(note.getBody() as String);
					pitemProxy.pitemsDP.addItem(pitemProxy.newProjectItem());
					break;
				case FFIAApplicationFacade.REFRESH_REFERENCE_LINES:
				case FFIAApplicationFacade.REFRESH_PITEMS:
					doLoadProjectItems();
					break;
            }
        }
        	
        public function doLoadProjectItems():void {
			pitemProxy.loadProjectItemByReference();
		}
        			
        public function makeEditor(event:AdvancedDataGridEvent):void {				
			event.preventDefault();
			var columnName:String = gridProjectItems.columns[event.columnIndex].dataField;
			var cbDataProvider:Object = null;
			var cbLabelFunction:Function = null;		
			var cbLabelField:String = null;		
			var cbKeyField:String = null;
			var useEditorComboBox = true;
			var sel:Object = gridProjectItems.dataProvider.getItemAt(gridProjectItems.selectedIndex);
			event.preventDefault();
			gridProjectItems.createItemEditor(event.columnIndex, event.rowIndex);
			var itemEditor:UIComponent = gridProjectItems.itemEditorInstance as UIComponent;
			var rawData = gridProjectItems.editedItemRenderer.data[columnName];
			if (rawData == null || rawData == undefined) {
				rawData = "";
			}
			var value:String = String(rawData);
			switch(columnName) {
				case 'pitem_item_id':
					cbDataProvider = masterdataProxy.projectItemsDP;
					useEditorComboBox = true;
					break;
				case 'pitem_currency':
					cbDataProvider = masterdataProxy.currenciesDP;
					useEditorComboBox = true;
					break;
				case 'pitem_container':
					cbDataProvider = masterdataProxy.containersDP;
					useEditorComboBox = true;
					break;
				case 'pitem_quantity_unit':
					cbDataProvider = masterdataProxy.unitsDP;
					useEditorComboBox = true;
					break;
				case 'pitem_weight_unit':
					cbDataProvider = masterdataProxy.unitsDP;
					useEditorComboBox = true;
					break;
				case 'pitem_volume_unit':
					cbDataProvider = masterdataProxy.unitsDP;
					useEditorComboBox = true;
					break;
				case 'pitem_stamp_date':
				case 'pitem_custom_date':
				case 'pitem_ETA_date':
				case 'pitem_delivery_date':
					DateField(itemEditor).selectedDate = DpUtils.parseDate(value);
					DateField(itemEditor).editable = true;
					DateField(itemEditor).setFocus();
					return;
				case 'pitem_inspection':
		 		case 'pitem_unloading':
		 			event.preventDefault();
	                CheckBox(gridProjectItems.itemEditorInstance).selected = Boolean(value) == true || Number(value) > 0;
	                CheckBox(gridProjectItems.itemEditorInstance).addEventListener(KeyboardEvent.KEY_DOWN, handleKeyArrow);
	                CheckBox(gridProjectItems.itemEditorInstance).setFocus();
	                return;
			}               
            if (useEditorComboBox && null != cbDataProvider){
            	// Disable copying data back to the control.
                event.preventDefault();
                gridProjectItems.createItemEditor(event.columnIndex, event.rowIndex);
                var cb:EditorComboBox = EditorComboBox(gridProjectItems.itemEditorInstance);
                cb.dataProvider = cbDataProvider;
                if (cbLabelFunction != null) {
                	cb.labelFunction = cbLabelFunction;
                }
                if (cbKeyField != null) {
                	cb.keyField = cbKeyField;
                }
                if (cbLabelField != null) {
                	cb.labelField = cbLabelField;
                }
                cb.selectedData = Number(value);
                cb.setFocus();
            } else {
            	event.preventDefault();
                gridProjectItems.createItemEditor(event.columnIndex, event.rowIndex);
                TextInput(gridProjectItems.itemEditorInstance).text = value;
                TextInput(gridProjectItems.itemEditorInstance).addEventListener(KeyboardEvent.KEY_DOWN, handleKeyArrow);
                TextInput(gridProjectItems.itemEditorInstance).selectionBeginIndex = 0;
                TextInput(gridProjectItems.itemEditorInstance).selectionEndIndex = value.length;
                
                TextInput(gridProjectItems.itemEditorInstance).setFocus();
            }
            
            setupValidator(columnName, gridProjectItems.itemEditorInstance);
        }
        
        public function handleKeyArrow(event:KeyboardEvent):void {
        	if (event.keyCode == Keyboard.DOWN || event.keyCode == Keyboard.UP) {
        		event.stopPropagation();
            	var newEvent:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, false, false, Keyboard.ENTER, Keyboard.ENTER, 13, event.ctrlKey, event.altKey, event.keyCode == Keyboard.UP);
            	var b:Boolean = event.currentTarget.dispatchEvent(newEvent);
        	}            	
        }
        
        //handle datagrid cell edit end event
        public function processData(event:AdvancedDataGridEvent):void {
        	if (event.reason == AdvancedDataGridEventReason.CANCELLED) {
        		return;
        	}        	
        	//validate data
        	var colName:String = event.dataField;
        	if (curValidator != null) {
	    		var vResult:ValidationResultEvent = curValidator.validate();
	    		if (vResult.type == ValidationResultEvent.INVALID) {
	    			event.preventDefault();
	    			projectItemScreen.enableSave = false;
	    			return;
	    		}
        	}
        	projectItemScreen.enableSave = true;
        	if (event.rowIndex == (gridProjectItems.dataProvider.length - 1)) {
        		var emptyItem:Object = pitemProxy.newProjectItem();
				gridProjectItems.dataProvider.addItem(emptyItem);
//				sendNotification(FFIAApplicationFacade.ADD_EMPTY_PITEM, emptyItem); 
			}
        }
        
        public function comboBoxLabelFunction(item:Object, column:AdvancedDataGridColumn):String {
        	switch (column.dataField) {
        		case 'pitem_item_id': 
        			return masterdataProxy.getItemById(item[column.dataField]) as String;
        		case 'pitem_container':
        			return masterdataProxy.getContainerById(item[column.dataField]);
        		case 'pitem_quantity_unit':
				case 'pitem_weight_unit':
				case 'pitem_volume_unit':
        			return masterdataProxy.getUnitById(item[column.dataField]);
        		case 'pitem_currency':
        			return masterdataProxy.getCurrencyById(item[column.dataField]);
        		default:
        			return '';
        	}
        }

        public function doRemoveProjectItem(selIndex:int):void {
        	if (selIndex < 0 || selIndex >= gridProjectItems.dataProvider.length) {
        		alert.error("You should select a row to remove");
        		return;
        	}
        	alert.confirm("Do you want to remove row at [" + (selIndex + 1) + "]?", function(e:CloseEvent) {
        		if (e.detail != Alert.YES) {
        			return;
        		}
        		RIALogger.debug(this, "Remove row at " + selIndex);
        		pitemProxy.removeProjectItem(selIndex);
        		doValidate();
        		gridProjectItems.selectedIndex = -1;
        		projectItemScreen.enableSave = true;
        	});
        }
        function setupValidator(columnName:String, itemEditor:Object):void {
        	switch (columnName) {
        		case 'pitem_invoice_amount':
        			projectItemScreen.priceValidator.source = itemEditor;
	        		projectItemScreen.priceValidator.property = 'text';
	        		projectItemScreen.priceValidator.required = false;
	        		curValidator = projectItemScreen.priceValidator;
	        		break;
        		case 'pitem_quantity':
        		case 'pitem_weight':
        		case 'pitem_volume':
        		case 'pitem_container_total':
        			projectItemScreen.quantityValidator.source = itemEditor;
	        		projectItemScreen.quantityValidator.property = 'text';
	        		projectItemScreen.quantityValidator.required = false;
	        		curValidator = projectItemScreen.quantityValidator;
	        		break;
	        	default:
	        		curValidator = null;
        	}
        }
        
        public function lfRowNum(item:Object, col:int):String {
        	if (Number(item.pitem_item_id) > 0) {
	        	return String(gridProjectItems.dataProvider.getItemIndex(item) + 1);
    		}
    		return "";
        }
        
        private var curValidator:Validator;
	}	
}